import random
import string
from datetime import datetime, timedelta
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from starlette.requests import Request

from exceptions.exception import ServiceException
from module_admin.dao.user_dao import UserDao
from module_admin.entity.do.user_do import SysUser
from module_admin.entity.vo.email_vo import EmailCodeRequest, ResetPasswordRequest
from module_admin.entity.vo.login_vo import EmailUserRegister
from module_admin.entity.vo.user_vo import AddUserModel
from module_admin.service.user_service import UserService
from module_admin.entity.vo.user_vo import EditUserModel
from utils.email_util import EmailUtil
from utils.pwd_util import PwdUtil
from utils.string_util import StringUtil


class EmailService:
    """邮箱服务层"""

    default_avatar = [
        "https://ppt85.oss-cn-beijing.aliyuncs.com/avatar/a65d19043c9edaa0dd8af640aec8c297.jpg",
        "https://ppt85.oss-cn-beijing.aliyuncs.com/avatar/94e31b0d7597192d64661bbbc54b9b54.jpg",
        "https://ppt85.oss-cn-beijing.aliyuncs.com/avatar/6cf211ed5e58d29635a0228f8c1f0614.jpeg",
        "https://ppt85.oss-cn-beijing.aliyuncs.com/avatar/10c995fbcdd213aaa04dc1d6fadef121.jpeg",
        "https://ppt85.oss-cn-beijing.aliyuncs.com/avatar/e23682c2fc740e10081fa4ac57171fee.jpeg",
        "https://ppt85.oss-cn-beijing.aliyuncs.com/avatar/b3d8c1208806efa41bbaea3163fae408.jpg",
        "https://ppt85.oss-cn-beijing.aliyuncs.com/avatar/8f080649263539020441b6f43ca952de.jpeg",
        "https://ppt85.oss-cn-beijing.aliyuncs.com/avatar/6e032fe7675eb411d92b6d50965f3979.jpg",
        "https://ppt85.oss-cn-beijing.aliyuncs.com/avatar/035c289fb73199803f63851339a59ea8.jpeg"

    ]

    @classmethod
    async def send_email_code(cls, request: Request, email_request: EmailCodeRequest, query_db: AsyncSession):
        """
        发送邮箱验证码
        """
        # 生成6位数字验证码
        verification_code = ''.join(random.choices(string.digits, k=4))
        
        # 将验证码存储到Redis，有效期5分钟
        redis_key = f"email_code:{email_request.type}:{email_request.email}"
        await request.app.state.redis.set(
            redis_key, 
            verification_code, 
            ex=300  # 5分钟过期
        )
        
        # 这里应该调用邮件服务发送验证码
        # 由于没有配置邮件服务，我们暂时打印到控制台
        print(f"邮箱验证码: {email_request.email} -> {verification_code}")
        EmailUtil.send_email(email_request.email, "85PPT验证码", f"欢迎使用85PPT，您的验证码是：{verification_code}")
        
        return {
            "email": email_request.email,
            "type": email_request.type,
            "expires_in": 300
        }

    @classmethod
    async def check_email_exists(cls, query_db: AsyncSession, email: str) -> bool:
        """
        检查邮箱是否已存在
        """
        stmt = select(SysUser).where(SysUser.email == email, SysUser.del_flag == '0')
        result = await query_db.execute(stmt)
        user = result.scalar_one_or_none()
        return user is not None

    @classmethod
    async def verify_email_code(cls, request: Request, email: str, code: str, code_type: str) -> bool:
        """
        验证邮箱验证码
        """
        redis_key = f"email_code:{code_type}:{email}"
        stored_code = await request.app.state.redis.get(redis_key)
        
        if not stored_code:
            raise ServiceException(message="验证码已过期或不存在")
        
        if stored_code != code:
            raise ServiceException(message="验证码错误")
        
        # 验证成功后删除验证码
        await request.app.state.redis.delete(redis_key)
        return True

    @classmethod
    async def reset_password(cls, request: Request, reset_request: ResetPasswordRequest, query_db: AsyncSession):
        """
        重置密码
        """
        # 验证邮箱验证码
        await cls.verify_email_code(request, reset_request.email, reset_request.verification_code, "reset")
        
        # 查找用户
        stmt = select(SysUser).where(SysUser.email == reset_request.email, SysUser.del_flag == '0')
        user = (await query_db.execute(stmt)).scalar_one_or_none()

        if not user:
            raise ServiceException(message="用户不存在")
        
        # 更新密码
        hashed_password = PwdUtil.get_password_hash(reset_request.new_password)
        await UserService.edit_user_services(
            query_db, 
            EditUserModel(
                userId=user.user_id, 
                password=hashed_password, 
                type='pwd'
            ),
            auto_commit=False
        )
        user_id = user.user_id
        await query_db.commit()
        return {
            "user_id": user_id,
            "email": reset_request.email
        }

    @classmethod
    async def register_with_email(cls, request: Request, register_request: EmailUserRegister, query_db: AsyncSession):
        """
        通过邮箱验证码注册用户
        """
        # 验证邮箱验证码
        await cls.verify_email_code(request, register_request.email, register_request.verification_code, "register")
        
        # 检查邮箱是否已存在
        if await cls.check_email_exists(query_db, register_request.email):
            raise ServiceException(message="该邮箱已被注册")
        
        # 自动生成随机用户名
        username = StringUtil.gen_short_id()
        
        # 创建用户
        add_user = AddUserModel(
            userName=username,
            nickName=username,
            email=register_request.email,
            deptId=204,
            password=PwdUtil.get_password_hash(register_request.password),
            roleIds=[101],
            avatar=random.choice(cls.default_avatar)
        )
        
        await UserService.add_user_services(query_db, add_user)
        
        # 处理推广关系
        if register_request.affiliate_code:
            from module_user.service.bg_user_affiliate_service import BgUserAffiliateService
            affiliate_service = BgUserAffiliateService()
            # 获取新创建的用户ID
            new_user = await UserDao.get_user_by_name(query_db, username)
            if new_user:
                await affiliate_service.process_user_registration(query_db, new_user.user_id, register_request.affiliate_code)
        
        return {
            "username": username,
            "email": register_request.email
        }
